/**
 * Copyright 2009 University of Washington This code is released under the GPL version 3 - with a copy of the license
 * included
 * 
 * @author Maya Hao Li
 * 
 */
package seedpod.model.rdb;

import java.io.PrintWriter;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;

import seedpod.kb2db.ClsMap;
import seedpod.model.ProtegeValueType;
import seedpod.model.RdbCls;
import seedpod.model.RdbSlot;
import seedpod.model.SeedpodModel;
import seedpod.rdb.RdbSql;
import seedpod.rdb.SqlUtil;

import edu.stanford.smi.protege.model.Cls;
import edu.stanford.smi.protege.model.Slot;

public class MetaRdbSlot {
	public static final String ALLOWED_CLS = "allowedCls";
	public static final String ALLOWED_VALUES = "symbolChoices";
	public static final String ATT_ID = "aid";
	public static final String RDB_SLOT_INVERSE = "slotInverse";
	public static final String CARD_MAX = "cardinalityMax";
	public static final String CARD_MIN = "cardinalityMin";
	public static final String DEFAULT_VALUE = "defaultValues";
	public static final String DOCUMENTATION = "documentation";
	public static final String DOMAIN = "domainCls";
	public static final String FORM_WIDGET = "formWidget";
	public static final String FORM_WIDGET_PARAM = "formWidgetParam";
	public static final String FRAME_ID = "frameID";
	public static final String FREE_EXPRESSION = "expression";
	public static final String IS_MULTIPLE = "isMultiple";
	public static final String IS_ASSOCIATED = "isAssociated";
	public static final String NAME = "name";
	public static final String NULLABLE = "nullable";
	public static final String NUM_MAX = "numericMax";
	public static final String NUM_MIN = "numericMin";
	public static final String PROTEGE_VALUE_TYPE = "protegeValueType";
	public static final String RDB_ATT_NAME = "rdbAttributeName";
	public static final String RDB_INDEX = "index";
	public static final String RDB_TARGET = "rdbTarget";
	public static final String RDB_VALUE_TYPE = "dbValueType";
	public static final String RDB_VALUE_LENGTH = "dbValueLength";
	public static final String SLOT_METACLS = "slotType";
	public static final String UNIQUE = "unique";
	public static final String UNIT = "unit";
	public static final String USER_DEFINED_NAME = "userDefinedName";
	public static final String VALUE_DELIMITER = "\t"; // "sp";
	public static final String VIEW_SEQUENCE = "viewSequence";
	public static final String VIEW_WIDGET = "viewWidget";
	public static final String VIEW_WIDGET_PARAM = "viewWidgetParam";
	public static final String AID = "aid";

	private static boolean _isTableInitialized = false;
	private static Relation _tblRdbAttribute;
	private HashMap<String, Object> _rdbSlotInstance = new HashMap<String, Object>();

	// creates an instance of MetaRdbSlot, which is a row in the :RDB_ATTRIBUTE table
	public static MetaRdbSlot create( RdbSlot rdbSlot, Attribute att ) {
		MetaRdbSlot instance = new MetaRdbSlot();
		instance.init( rdbSlot, att );
		return instance;
	}

	public static MetaRdbSlot create( RdbSlot rdbSlot, RdbCls rdbCls ) {
		MetaRdbSlot instance = new MetaRdbSlot();
		instance.init( rdbSlot, rdbCls );
		return instance;
	}

	public static MetaRdbSlot create( ResultSet rs ) throws SQLException {
		MetaRdbSlot instance = new MetaRdbSlot();
		instance.init( rs );
		return instance;
	}

	public static void serializeSchema( PrintWriter out ) {
		out.println( RdbSql.createTable( _tblRdbAttribute ) );
	}

	public MetaRdbSlot() {
		if ( !_isTableInitialized ) {
			_isTableInitialized = true;
			new MetaRdbSlotRelation();
		}
	}

	public String getAllowedCls() {
		return (String)_rdbSlotInstance.get( ALLOWED_CLS );
	}

	public String getSlotInverse() {
		return (String)_rdbSlotInstance.get( RDB_SLOT_INVERSE );
	}

	public String getAllowedValues() {
		return (String)_rdbSlotInstance.get( ALLOWED_VALUES );
	}

	public Integer getAtributeID() {
		return (Integer)_rdbSlotInstance.get( AID );
	}

	/**
	 * same as MetaRdbSlot.getName()
	 * 
	 * @return
	 */
	public String getAttributeName() {
		return (String)_rdbSlotInstance.get( NAME );
	}

	public Integer getCardinalityMax() {
		return (Integer)_rdbSlotInstance.get( CARD_MAX );
	}

	public Integer getCardinalityMin() {
		return (Integer)_rdbSlotInstance.get( CARD_MIN );
	}

	public String getDefaultValue() {
		return (String)_rdbSlotInstance.get( DEFAULT_VALUE );
	}

	public String getDocumentation() {
		return (String)_rdbSlotInstance.get( DOCUMENTATION );
	}

	public String getDomain() {
		return (String)_rdbSlotInstance.get( DOMAIN );
	}

	public String getFormWidget() {
		return (String)_rdbSlotInstance.get( FORM_WIDGET );
	}

	public String getFormWidgetParam() {
		return (String)_rdbSlotInstance.get( FORM_WIDGET_PARAM );

	}

	public Integer getFrameId() {
		return (Integer)_rdbSlotInstance.get( FRAME_ID );
	}

	public String getFreeExpression() {
		return (String)_rdbSlotInstance.get( FREE_EXPRESSION );
	}

	public Boolean getIsNullable() {
		return (Boolean)_rdbSlotInstance.get( NULLABLE );
	}

	public String getName() {
		return (String)_rdbSlotInstance.get( NAME );
	}

	public Double getNumericMax() {
		return (Double)_rdbSlotInstance.get( NUM_MAX );
	}

	public Double getNumericMin() {
		return (Double)_rdbSlotInstance.get( NUM_MIN );
	}

	public ProtegeValueType getProtegeValueType() {
		return ProtegeValueType.valueOf( (String)_rdbSlotInstance.get( PROTEGE_VALUE_TYPE ) );
	}

	public String getRdbAttName() {
		return (String)_rdbSlotInstance.get( RDB_ATT_NAME );
	}

	public String getRdbTarget() {
		return (String)_rdbSlotInstance.get( RDB_TARGET );
	}

	public RdbValueType getRdbValueType() {
		return (RdbValueType)_rdbSlotInstance.get( RDB_VALUE_TYPE );
	}

	public Integer getRdbValueLength() {
		return (Integer)_rdbSlotInstance.get( RDB_VALUE_LENGTH );
	}

	public HashMap<String, Object> getSlotInstanceData() {
		return _rdbSlotInstance;
	}

	public String getSlotType() {
		return (String)_rdbSlotInstance.get( SLOT_METACLS );
	}

	public static String getTargetString( Attribute att ) {
		if ( !att.isImplemented() ) {
			Attribute inverse = att.getInverseAttribute();
			if ( inverse != null ) return SeedpodModel.DEFAULT_META_RDB_SLOT + SqlUtil.PARAN( inverse.getName() );

		}

		return SeedpodModel.DEFAULT_META_RDB_SLOT + SqlUtil.PARAN( att.getName() );
	}

	public static String getTargetString( RdbCls cls ) {
		return SeedpodModel.DEFAULT_META_RDB_CLASS + SqlUtil.PARAN( cls.getName() );
	}

	public static String getTargetString( ClsMap clsMap ) {
		return SeedpodModel.DEFAULT_META_RDB_CLASS + SqlUtil.PARAN( clsMap.getName() );
	}

	public String getUnit() {
		return (String)_rdbSlotInstance.get( UNIT );
	}

	public String getUserDefinedName() {
		return (String)_rdbSlotInstance.get( USER_DEFINED_NAME );
	}

	public Float getViewSequence() {
		return (Float)_rdbSlotInstance.get( VIEW_SEQUENCE );
	}

	public String getViewWidget() {
		return (String)_rdbSlotInstance.get( VIEW_WIDGET );
	}

	public String getViewWidgetParam() {
		return (String)_rdbSlotInstance.get( VIEW_WIDGET_PARAM );
	}

	private void init( RdbSlot rdbSlot, Attribute att ) {
		_rdbSlotInstance = new HashMap<String, Object>();
		if ( rdbSlot != null ) setSlotProperties( rdbSlot );
		if ( att != null ) setAttributeProperties( att );
	}

	public void init( ResultSet rs ) throws SQLException {
		_rdbSlotInstance = new HashMap<String, Object>();
		setAttributeID( rs.getInt( AID ) );
		setFrameId( rs.getInt( FRAME_ID ) );
		setDomain( rs.getString( DOMAIN ) );
		setAttributeName( rs.getString( NAME ) );
		setUserDefinedName( rs.getString( USER_DEFINED_NAME ) );
		setSlotType( rs.getString( SLOT_METACLS ) );
		setValueType( rs.getString( PROTEGE_VALUE_TYPE ) );
		setDefaultValue( rs.getString( DEFAULT_VALUE ) );
		setAllowedCls( rs.getString( ALLOWED_CLS ) );
		setSlotInverse( rs.getString( RDB_SLOT_INVERSE ) );
		setNumericMin( rs.getDouble( NUM_MIN ) );
		setNumericMax( rs.getDouble( NUM_MAX ) );
		setCardinalityMin( rs.getInt( CARD_MIN ) );
		setCardinalityMax( rs.getInt( CARD_MAX ) );
		setNullable( rs.getBoolean( NULLABLE ) );
		setIsMultiple( rs.getBoolean( IS_MULTIPLE ) );
		setIsUnique( rs.getBoolean( UNIQUE ) );
		setIsIndexed( rs.getBoolean( RDB_INDEX ) );
		setAllowedValues( rs.getString( ALLOWED_VALUES ) );
		setUnit( rs.getString( UNIT ) );
		setDocumentation( rs.getString( DOCUMENTATION ) );

		setExpression( rs.getString( FREE_EXPRESSION ) );
		setViewSequence( rs.getFloat( VIEW_SEQUENCE ) );
		setFormWidget( rs.getString( FORM_WIDGET ) );
		setFormWidgetParam( rs.getString( FORM_WIDGET_PARAM ) );
		setViewWidget( rs.getString( VIEW_WIDGET ) );
		setViewWidgetParam( rs.getString( VIEW_WIDGET_PARAM ) );

		setRdbAttName( rs.getString( RDB_ATT_NAME ) );
		setRdbAttTarget( rs.getString( RDB_TARGET ) );
		setIsAssociated( rs.getBoolean( IS_ASSOCIATED ) );
		setRdbValueType( RdbValueType.valueOf( rs.getString( RDB_VALUE_TYPE ) ) );
		setRdbValueLength( rs.getInt( RDB_VALUE_LENGTH ) );
	}

	public Boolean isIndexed() {
		return (Boolean)_rdbSlotInstance.get( RDB_INDEX );
	}

	public Boolean isMultiple() {
		return (Boolean)_rdbSlotInstance.get( IS_MULTIPLE );
	}

	public Boolean isUnique() {
		return (Boolean)_rdbSlotInstance.get( UNIQUE );
	}

	public Boolean isAssociated() {
		return (Boolean)_rdbSlotInstance.get( IS_ASSOCIATED );
	}

	public void serializeInstance( PrintWriter out ) {
		out.println( genInsertSatement( _tblRdbAttribute, getSlotInstanceData() ) );
	}

	/**
	 * TODO injection risk in inserting string values w/ single quote. consider using getInsertPreparedStatement
	 * instead.*
	 */
	public static String genInsertSatement( Relation rel, HashMap<String, Object> data ) {
		String insertStmt = "INSERT INTO " + SqlUtil.SP + SqlUtil.QQ( rel.getName() ) + SqlUtil.NL + SqlUtil.TAB;
		String keyString = "", valString = "";
		for ( Attribute att : rel.getAttributes() ) {
			Object val = data.get( att.getName() ) ;
			keyString += SqlUtil.QQ( att.getName() ) + SqlUtil.C;
			try {
				valString += RdbSql.toSqlValString( val, att ) +SqlUtil.C;
			} catch (Exception exc) {
				System.err.println( exc.getMessage() );
				System.err.println( "errr in RdbSql.insertRowSql " + rel.getName() + " " + att.getName() + " is null.  The errorneous SQL is commented out with -- in the output files. " );

				return " -- Insert statement terminated:  " + valString;
			}
		}

		keyString = keyString.substring( 0, keyString.lastIndexOf( SqlUtil.C ) - 1 );
		valString = valString.substring( 0, valString.lastIndexOf( SqlUtil.C ) - 1 );
		insertStmt += SqlUtil.PARAN( keyString ) + SqlUtil.NL + " VALUES " + SqlUtil.PARAN( valString ) + SqlUtil.SC;
		return insertStmt;
	}

	public void setAttributeID( Integer id ) {
		_rdbSlotInstance.put( AID, id );
	}

	// this is a ref to the cid of the domain cls, not the cls itself
	public void setAllowedCls( String allowedCls ) {
		if ( allowedCls != null )
			_rdbSlotInstance.put( ALLOWED_CLS, allowedCls );
		else _rdbSlotInstance.put( ALLOWED_CLS, null );
	}

	private void setSlotInverse( String inverseSlotName ) {
		if ( inverseSlotName != null )
			_rdbSlotInstance.put( RDB_SLOT_INVERSE, inverseSlotName );
		else _rdbSlotInstance.put( RDB_SLOT_INVERSE, null );
	}

	public void setAllowedValues( Collection<String> allowedValues ) {
		if ( allowedValues.isEmpty() )
			_rdbSlotInstance.put( ALLOWED_VALUES, null );
		else {
			Iterator<String> valIter = allowedValues.iterator();
			String valString = (String)valIter.next();
			while (valIter.hasNext()) {
				valString += VALUE_DELIMITER + (String)valIter.next();
			}
			_rdbSlotInstance.put( ALLOWED_VALUES, valString );
		}
	}

	public void setAttributeName( String name2 ) {
		_rdbSlotInstance.put( NAME, name2 );
	}

	public void setCardinalityMax( int integer ) {
		_rdbSlotInstance.put( CARD_MAX, new Integer( integer ) );
	}

	public void setCardinalityMin( int integer ) {
		_rdbSlotInstance.put( CARD_MIN, new Integer( integer ) );
	}

	public void setDefaultValue( String defaultValue ) {
		_rdbSlotInstance.put( DEFAULT_VALUE, defaultValue );
	}

	// only stores the first entry
	public void setDocumentation( Collection<String> documentation ) {
		if ( documentation.isEmpty() )
			_rdbSlotInstance.put( DOCUMENTATION, "" );
		else {
			_rdbSlotInstance.put( DOCUMENTATION, (String)documentation.iterator().next() );
		}
	}

	public void setDomain( String name2 ) {
		_rdbSlotInstance.put( DOMAIN, name2 );
	}

	public void setExpression( String expression ) {
		_rdbSlotInstance.put( FREE_EXPRESSION, expression );
	}

	public void setFormWidget( String formWidget ) {
		_rdbSlotInstance.put( FORM_WIDGET, formWidget );
	}

	public void setFormWidgetParam( String formWidgetParameter ) {
		_rdbSlotInstance.put( FORM_WIDGET_PARAM, formWidgetParameter );
	}

	public void setFrameId( int integer ) {
		_rdbSlotInstance.put( FRAME_ID, new Integer( integer ) );
	}

	public void setIsIndexed( boolean b ) {
		_rdbSlotInstance.put( RDB_INDEX, new Boolean( b ) );
	}

	public void setIsMultiple( boolean b ) {
		_rdbSlotInstance.put( IS_MULTIPLE, new Boolean( b ) );
	}

	public void setIsUnique( boolean b ) {
		_rdbSlotInstance.put( UNIQUE, new Boolean( b ) );
	}

	public void setIsAssociated( boolean b ) {
		_rdbSlotInstance.put( IS_ASSOCIATED, new Boolean( b ) );
	}

	public void setNullable( boolean b ) {
		_rdbSlotInstance.put( NULLABLE, new Boolean( b ) );
	}

	public void setNumericMax( Number maximumValue ) {
		if ( maximumValue != null )
			_rdbSlotInstance.put( NUM_MAX, maximumValue.floatValue() );
		else _rdbSlotInstance.put( NUM_MAX, null );
	}

	public void setNumericMin( Number minimumValue ) {
		if ( minimumValue != null )
			_rdbSlotInstance.put( NUM_MIN, minimumValue.floatValue() );
		else _rdbSlotInstance.put( NUM_MIN, null );
	}

	public void setRdbAttName( String attName ) {
		_rdbSlotInstance.put( RDB_ATT_NAME, attName );
	}

	public void setRdbAttTarget( String targetString ) {
		_rdbSlotInstance.put( RDB_TARGET, targetString );
	}

	public void setRdbValueType( RdbValueType databaseType ) {
		_rdbSlotInstance.put( RDB_VALUE_TYPE, databaseType );
	}

	public void setRdbValueLength( Integer valueLength ) {
		_rdbSlotInstance.put( RDB_VALUE_LENGTH, valueLength );
	}

	public void setSlotType( String name2 ) {
		_rdbSlotInstance.put( SLOT_METACLS, name2 );
	}

	public void setUnit( String unit ) {
		_rdbSlotInstance.put( UNIT, unit );
	}

	public void setUserDefinedName( String userDefinedName ) {
		_rdbSlotInstance.put( USER_DEFINED_NAME, userDefinedName );
	}

	public void setValueType( String valueType ) {
		_rdbSlotInstance.put( PROTEGE_VALUE_TYPE, valueType );
	}

	public void setViewSequence( Float viewSequence ) {
		_rdbSlotInstance.put( VIEW_SEQUENCE, viewSequence );
	}

	public void setViewWidget( String viewWidget ) {
		_rdbSlotInstance.put( VIEW_WIDGET, viewWidget );
	}

	public void setViewWidgetParam( String viewWidgetParameter ) {
		_rdbSlotInstance.put( VIEW_WIDGET_PARAM, viewWidgetParameter );
	}

	// initializing an rdbSlot
	private void init( RdbSlot rdbSlot, RdbCls rdbCls ) {
		_rdbSlotInstance = new HashMap<String, Object>();
		if ( rdbSlot != null ) setSlotProperties( rdbSlot );
		if ( rdbCls != null ) setAttributeProperties( rdbCls );
	}

	public void setAllowedCls( Cls allowedCls ) {
		String name = (allowedCls == null) ? "" : allowedCls.getName();
		setAllowedCls( name );
	}

	public void setSlotInverse( RdbSlot inverse ) {
		String iSlot = (inverse == null) ? "" : inverse.getName();
		setSlotInverse( iSlot );
	}

	public void setAllowedValues( String valString ) {
		_rdbSlotInstance.put( ALLOWED_VALUES, valString );
	}

	public void setDocumentation( String string ) {
		_rdbSlotInstance.put( DOCUMENTATION, string );
	}

	private void setAttributeProperties( Attribute att ) {
		setRdbAttName( att.getName() );
		setRdbAttTarget( getTargetString( att ) );
		setIsAssociated( att.isImplemented() );
		setRdbValueType( att.getRdbValueType() );
		setRdbValueLength( att.getRdbValueLength() );
	}

	private void setAttributeProperties( RdbCls cls ) {
		setRdbAttTarget( getTargetString( cls ) );
		setIsAssociated( false );
		setRdbValueType( RdbValueType.RELATION );
	}

	@SuppressWarnings("unchecked")
	private void setSlotProperties( RdbSlot rdbSlot ) {
		Slot slot = rdbSlot.getSlot();
		setFrameId( slot.getFrameID().getLocalPart() );
		setDomain( rdbSlot.getDomainCls().getName() );
		setAttributeName( rdbSlot.getName() );
		setUserDefinedName( rdbSlot.getUserDefinedName() );
		setSlotType( slot.getDirectType().getName() );
		setValueType( rdbSlot.getValueType().toString() );
		setDefaultValue( rdbSlot.getDefaultValue() );
		setAllowedCls( rdbSlot.getAllowedCls() );
		setSlotInverse( rdbSlot.getInverse() );
		setNumericMin( slot.getMinimumValue() );
		setNumericMax( slot.getMaximumValue() );
		setCardinalityMin( slot.getMinimumCardinality() );
		setCardinalityMax( slot.getMaximumCardinality() );
		setNullable( !rdbSlot.isRequired() );
		setIsMultiple( rdbSlot.allowsMultipleValues() );
		setIsUnique( rdbSlot.isUnique() );
		setIsIndexed( rdbSlot.isIndexed() );
		setAllowedValues( slot.getAllowedValues() );
		setUnit( rdbSlot.getUnit() );
		setDocumentation( slot.getDocumentation() );

		setExpression( rdbSlot.getExpression() );
		setViewSequence( rdbSlot.getViewSequence() );
		setFormWidget( rdbSlot.getFormWidget() );
		setFormWidgetParam( rdbSlot.getFormWidgetParameter() );
		setViewWidget( rdbSlot.getViewWidget() );
		setViewWidgetParam( rdbSlot.getViewWidgetParameter() );
	}

	/**
	 * class MetaRdbSlotRelation
	 */
	class MetaRdbSlotRelation {
		public MetaRdbSlotRelation() {
			_tblRdbAttribute = new Relation( SeedpodModel.DEFAULT_META_RDB_SLOT );
			initRdbSlotTable();
		}

		public Relation getRelation() {
			return _tblRdbAttribute;
		}

		private void initRdbSlotTable() {
			Attribute att_cid = new Attribute( _tblRdbAttribute, ATT_ID, RdbValueType.SERIAL, true, null );

			Attribute att_frameID = new Attribute( _tblRdbAttribute, FRAME_ID, RdbValueType.INTEGER, false, null );

			Attribute att_domain = new Attribute( _tblRdbAttribute, DOMAIN, RdbValueType.VARCHAR, true, null );
			att_domain.setDatabaseParameter( Rdb.MAX_NAME_LENGTH );

			Attribute att_name = new Attribute( _tblRdbAttribute, NAME, RdbValueType.VARCHAR, true, null );
			att_name.setDatabaseParameter( Rdb.MAX_NAME_LENGTH );
			// att_name.setIsUnique( true );

			Attribute att_userName = new Attribute( _tblRdbAttribute, USER_DEFINED_NAME, RdbValueType.TEXT, false, null );

			Attribute att_type = new Attribute( _tblRdbAttribute, SLOT_METACLS, RdbValueType.VARCHAR, true, SeedpodModel.DEFAULT_META_RDB_CLASS );
			att_type.setDatabaseParameter( Rdb.MAX_NAME_LENGTH );

			Attribute att_protegeType = new Attribute( _tblRdbAttribute, PROTEGE_VALUE_TYPE, RdbValueType.VARCHAR, true, null );
			att_type.setDatabaseParameter( 32 );

			Attribute att_defaultVal = new Attribute( _tblRdbAttribute, DEFAULT_VALUE, RdbValueType.TEXT, false, null );

			Attribute att_allowedCls = new Attribute( _tblRdbAttribute, ALLOWED_CLS, RdbValueType.VARCHAR, false, null );
			att_allowedCls.setDatabaseParameter( Rdb.MAX_NAME_LENGTH );

			Attribute att_slotInverse = new Attribute( _tblRdbAttribute, RDB_SLOT_INVERSE, RdbValueType.VARCHAR, false, null );
			att_slotInverse.setDatabaseParameter( Rdb.MAX_NAME_LENGTH );

			Attribute att_num_min = new Attribute( _tblRdbAttribute, NUM_MIN, RdbValueType.NUMERIC, false, null );
			Attribute att_num_max = new Attribute( _tblRdbAttribute, NUM_MAX, RdbValueType.NUMERIC, false, null );
			Attribute att_card_min = new Attribute( _tblRdbAttribute, CARD_MIN, RdbValueType.INTEGER, false, "0" );
			Attribute att_card_max = new Attribute( _tblRdbAttribute, CARD_MAX, RdbValueType.INTEGER, false, null );
			Attribute att_nullable = new Attribute( _tblRdbAttribute, NULLABLE, RdbValueType.BOOLEAN, true, "true" );
			Attribute att_isMultiple = new Attribute( _tblRdbAttribute, IS_MULTIPLE, RdbValueType.BOOLEAN, true, "false" );

			Attribute att_unique = new Attribute( _tblRdbAttribute, UNIQUE, RdbValueType.BOOLEAN, false, "false" );
			Attribute att_index = new Attribute( _tblRdbAttribute, RDB_INDEX, RdbValueType.BOOLEAN, false, "false" );

			Attribute att_allowedValues = new Attribute( _tblRdbAttribute, ALLOWED_VALUES, RdbValueType.TEXT, false, null );
			Attribute att_unit = new Attribute( _tblRdbAttribute, UNIT, RdbValueType.VARCHAR, false, null );
			att_unit.setDatabaseParameter( 32 );
			Attribute att_documentation = new Attribute( _tblRdbAttribute, DOCUMENTATION, RdbValueType.TEXT, false, "" );

			Attribute att_rdbAttName = new Attribute( _tblRdbAttribute, RDB_ATT_NAME, RdbValueType.VARCHAR, true, null );
			att_rdbAttName.setDatabaseParameter( Rdb.MAX_NAME_LENGTH );

			// slots are mapped to attribute, table, or foreign key
			Attribute att_rdbMapToTarget = new Attribute( _tblRdbAttribute, RDB_TARGET, RdbValueType.VARCHAR, true, "ATTRIBUTE" );
			att_rdbMapToTarget.setDatabaseParameter( 100 );

			Attribute att_rdbValueType = new Attribute( _tblRdbAttribute, RDB_VALUE_TYPE, RdbValueType.VARCHAR, false, null );
			att_rdbValueType.setDatabaseParameter( 36 );

			Attribute att_rdbValueLength = new Attribute( _tblRdbAttribute, RDB_VALUE_LENGTH, RdbValueType.INTEGER, false, null );

			Attribute att_isAssociated = new Attribute( _tblRdbAttribute, IS_ASSOCIATED, RdbValueType.BOOLEAN, true, "true" );

			Attribute att_expression = new Attribute( _tblRdbAttribute, FREE_EXPRESSION, RdbValueType.TEXT, false, "NULL" );
			Attribute att_viewSequence = new Attribute( _tblRdbAttribute, VIEW_SEQUENCE, RdbValueType.NUMERIC, false, "NULL" );

			Attribute att_formWidget = new Attribute( _tblRdbAttribute, FORM_WIDGET, RdbValueType.VARCHAR, false, "NULL" );
			att_formWidget.setDatabaseParameter( 50 );

			Attribute att_formWidgetParam = new Attribute( _tblRdbAttribute, FORM_WIDGET_PARAM, RdbValueType.VARCHAR, false, "NULL" );
			att_formWidgetParam.setDatabaseParameter( 255 );

			Attribute att_viewWidget = new Attribute( _tblRdbAttribute, VIEW_WIDGET, RdbValueType.VARCHAR, false, "NULL" );
			att_viewWidget.setDatabaseParameter( 50 );

			Attribute att_viewWidgetParam = new Attribute( _tblRdbAttribute, VIEW_WIDGET_PARAM, RdbValueType.VARCHAR, false, "NULL" );
			att_viewWidgetParam.setDatabaseParameter( 255 );

			_tblRdbAttribute.setPrimaryKey( att_cid );
			_tblRdbAttribute.addAttribute( att_cid );
			_tblRdbAttribute.addAttribute( att_frameID );
			_tblRdbAttribute.addAttribute( att_domain );
			_tblRdbAttribute.addAttribute( att_name );
			_tblRdbAttribute.addAttribute( att_userName );
			_tblRdbAttribute.addAttribute( att_type );
			_tblRdbAttribute.addAttribute( att_protegeType );
			_tblRdbAttribute.addAttribute( att_defaultVal );
			_tblRdbAttribute.addAttribute( att_allowedCls );
			_tblRdbAttribute.addAttribute( att_slotInverse );
			_tblRdbAttribute.addAttribute( att_num_min );
			_tblRdbAttribute.addAttribute( att_num_max );
			_tblRdbAttribute.addAttribute( att_card_min );
			_tblRdbAttribute.addAttribute( att_card_max );
			_tblRdbAttribute.addAttribute( att_nullable );
			_tblRdbAttribute.addAttribute( att_isMultiple );
			_tblRdbAttribute.addAttribute( att_unique );
			_tblRdbAttribute.addAttribute( att_index );
			_tblRdbAttribute.addAttribute( att_allowedValues );
			_tblRdbAttribute.addAttribute( att_unit );
			_tblRdbAttribute.addAttribute( att_documentation );
			_tblRdbAttribute.addAttribute( att_rdbAttName );
			_tblRdbAttribute.addAttribute( att_rdbMapToTarget );
			_tblRdbAttribute.addAttribute( att_rdbValueType );
			_tblRdbAttribute.addAttribute( att_rdbValueLength );
			_tblRdbAttribute.addAttribute( att_isAssociated );
			_tblRdbAttribute.addAttribute( att_expression );
			_tblRdbAttribute.addAttribute( att_viewSequence );
			_tblRdbAttribute.addAttribute( att_formWidget );
			_tblRdbAttribute.addAttribute( att_formWidgetParam );
			_tblRdbAttribute.addAttribute( att_viewWidget );
			_tblRdbAttribute.addAttribute( att_viewWidgetParam );

		}

	}

}
